/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using ModuleResolver = System.Qizx.Api.ModuleResolver;
using Check = System.Qizx.Util.Basic.Check;
namespace System.Qizx.Api.Util {

    /// <summary> Default ModuleResolver implementation using a base URL.
    /// <p>
    /// The strategy used consists of appending the module namespace URI to the base
    /// URI, and (if possible) checking the existence of the pointed resource.
    /// <p>
    /// If the check fails, and if location hints are provided, then each hint is
    /// appended to the base URL and put to the result list, unless it can be
    /// verified that the URL formed this way points to a non-existent resource.
    /// </summary>
    public class DefaultModuleResolver : ModuleResolver {
        private System.Uri _baseURI;

        /// <summary> Creates a resolver using a base URL. </summary>
        /// <param name="base">an URL used as a base for resolving module URI's. 
        /// </param>
        public DefaultModuleResolver(System.Uri baseURI) {
            Check.nonNull(baseURI, "base URL");
            this._baseURI = baseURI;
            // due to weird behavior of URL class, need a trailing slash:
            if (baseURI != null && !baseURI.AbsolutePath.EndsWith("/")) {
                try {
                    System.UriBuilder temp_uriBuilder;
                    temp_uriBuilder = new System.UriBuilder(baseURI.Scheme, baseURI.Host);
                    temp_uriBuilder.Path = baseURI.AbsolutePath + "/";
                    this._baseURI = temp_uriBuilder.Uri;
                } catch (System.UriFormatException e) {
                    // what to do ?
                    SupportClass.WriteStackTrace(e, Console.Error);
                }
            }
        }

        /// <seealso cref="System.Qizx.Api.ModuleResolver.resolve">
        /// </seealso>
        public virtual System.Uri[] resolve(string moduleNamespaceURI, System.String[] locationHints) {
            System.Uri attempt = new System.Uri(_baseURI, moduleNamespaceURI);

            if (!nonExistentFile(attempt))
                return new System.Uri[] { attempt };
            // try hints:
            if (locationHints == null || locationHints.Length == 0)
                return new System.Uri[0]; // failure
            int hintCnt = locationHints.Length;
            System.Collections.ArrayList result = new System.Collections.ArrayList(hintCnt);
            for (int i = 0; i < locationHints.Length; i++) {
                System.Uri url = new System.Uri(_baseURI, locationHints[i]);

                if (!nonExistentFile(url))
                    result.Add(url);
            }
            return (System.Uri[])result.ToArray();
        }

        // returns true if file: and (does not exist or not plain)
        private bool nonExistentFile(System.Uri url) {
            if (!"file".Equals(url.Scheme))
                return false;
            System.IO.FileInfo file = new System.IO.FileInfo(url.AbsolutePath);
            return !System.IO.File.Exists(file.FullName);
        }
    }
}